From d247e5707dc8df5e32aee923ed317845cf4fec93 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 19 Feb 2019 05:50:49 +0100 Subject: [PATCH] widget: Fix gtk_widget_size_allocate() Compute the matrix for adjusted sizes etc properly. --- gtk/gtksizerequest.c | 3 +- gtk/gtkwidget.c | 165 +++++++++++++++-------------------------- gtk/gtkwidgetprivate.h | 2 +- 3 files changed, 63 insertions(+), 107 deletions(-) diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c index d14b55471a..197d2413ea 100644 --- a/gtk/gtksizerequest.c +++ b/gtk/gtksizerequest.c @@ -208,6 +208,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget, int adjusted_for_size; int minimum_for_size = 0; int natural_for_size = 0; + int dummy = 0; /* Pull the minimum for_size from the cache as it's needed to adjust * the proposed 'for_size' */ @@ -221,7 +222,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget, adjusted_for_size = for_size; gtk_widget_adjust_size_allocation (widget, OPPOSITE_ORIENTATION (orientation), &for_size, &natural_for_size, - NULL, &adjusted_for_size); + &dummy, &adjusted_for_size); adjusted_for_size -= css_extra_for_size; diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 4e6ea25321..6255aba57d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -4188,11 +4188,7 @@ gtk_widget_allocate (GtkWidget *widget, const graphene_matrix_t *transform) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); - int real_width; - int real_height; - int adjusted_width; - int adjusted_height; - graphene_matrix_t adjusted_transform; + GdkRectangle adjusted; gboolean alloc_needed; gboolean size_changed; gboolean baseline_changed; @@ -4249,9 +4245,7 @@ gtk_widget_allocate (GtkWidget *widget, priv->allocated_height = height; priv->allocated_size_baseline = baseline; - adjusted_width = width; - adjusted_height = height; - graphene_matrix_init_from_matrix (&adjusted_transform, transform); + adjusted = (GdkRectangle) { 0, 0, width, height }; if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) { /* Go ahead and request the height for allocated width, note that the internals @@ -4291,47 +4285,52 @@ gtk_widget_allocate (GtkWidget *widget, GTK_ORIENTATION_HORIZONTAL, &dummy, &natural_width, - &adjusted_transform, - &adjusted_width); + &adjusted.x, + &adjusted.width); gtk_widget_adjust_size_allocation (widget, GTK_ORIENTATION_VERTICAL, &dummy, &natural_height, - &adjusted_transform, - &adjusted_height); + &adjusted.y, + &adjusted.height); if (baseline >= 0) baseline -= priv->margin.top; - real_width = adjusted_width; - real_height = adjusted_height; - - if (real_width < 0 || real_height < 0) + if (adjusted.width < 0 || adjusted.height < 0) { g_warning ("gtk_widget_size_allocate(): attempt to allocate %s %s %p with width %d and height %d", G_OBJECT_TYPE_NAME (widget), gtk_css_node_get_name (priv->cssnode), widget, - real_width, - real_height); + adjusted.width, + adjusted.height); - real_width = 0; - real_height = 0; + adjusted.width = 0; + adjusted.height = 0; } if (G_UNLIKELY (_gtk_widget_get_has_surface (widget))) { - real_width = MAX (1, real_width); - real_height = MAX (1, real_height); + adjusted.width = MAX (1, adjusted.width); + adjusted.height = MAX (1, adjusted.height); } style = gtk_css_node_get_style (priv->cssnode); get_box_margin (style, &margin); get_box_border (style, &border); get_box_padding (style, &padding); - graphene_matrix_translate (&adjusted_transform, - &GRAPHENE_POINT3D_INIT ( - margin.left + border.left + padding.left, - margin.top + border.top + padding.top, - 0 - )); + adjusted.x += margin.left + border.left + padding.left; + adjusted.y += margin.top + border.top + padding.top; + + /* Since gtk_widget_measure does it for us, we can be sure here that + * the given alloaction is large enough for the css margin/bordder/padding */ + adjusted.width -= margin.left + border.left + padding.left + + margin.right + border.right + padding.right; + adjusted.height -= margin.top + border.top + padding.top + + margin.bottom + border.bottom + padding.bottom; + if (baseline >= 0) + baseline -= margin.top + border.top + padding.top; + + graphene_matrix_init_translate (&priv->transform, &GRAPHENE_POINT3D_INIT (adjusted.x, adjusted.y, 0)); + graphene_matrix_multiply (&priv->transform, transform, &priv->transform); if (!alloc_needed && !size_changed && !baseline_changed) { @@ -4347,20 +4346,11 @@ gtk_widget_allocate (GtkWidget *widget, window_alloc.width, window_alloc.height); } - goto only_transform_changed; + goto skip_allocate; } - /* Since gtk_widget_measure does it for us, we can be sure here that - * the given alloaction is large enough for the css margin/bordder/padding */ - real_width -= margin.left + border.left + padding.left + - margin.right + border.right + padding.right; - real_height -= margin.top + border.top + padding.top + - margin.bottom + border.bottom + padding.bottom; - if (baseline >= 0) - baseline -= margin.top + border.top + padding.top; - - priv->width = real_width; - priv->height = real_height; + priv->width = adjusted.width; + priv->height = adjusted.height; priv->baseline = baseline; if (g_signal_has_handler_pending (widget, widget_signals[SIZE_ALLOCATE], 0, FALSE)) @@ -4389,9 +4379,7 @@ gtk_widget_allocate (GtkWidget *widget, gtk_widget_update_paintables (widget); -only_transform_changed: - graphene_matrix_init_from_matrix (&priv->transform, &adjusted_transform); - +skip_allocate: if (size_changed || baseline_changed) gtk_widget_queue_draw (widget); else if (transform_changed && priv->parent) @@ -4616,11 +4604,10 @@ effective_align (GtkAlign align, } static void -adjust_for_align (GtkOrientation orientation, - GtkAlign align, - int *natural_size, - graphene_matrix_t *transform, - int *allocated_size) +adjust_for_align (GtkAlign align, + gint *natural_size, + gint *allocated_pos, + gint *allocated_size) { switch (align) { @@ -4630,66 +4617,38 @@ adjust_for_align (GtkOrientation orientation, /* change nothing */ break; case GTK_ALIGN_START: - /* keep position where it is */ + /* keep *allocated_pos where it is */ *allocated_size = MIN (*allocated_size, *natural_size); break; case GTK_ALIGN_END: if (*allocated_size > *natural_size) - { - if (transform) - { - if (orientation == GTK_ORIENTATION_HORIZONTAL) - graphene_matrix_translate (transform, - &GRAPHENE_POINT3D_INIT (*allocated_size - *natural_size, 0, 0)); - else - graphene_matrix_translate (transform, - &GRAPHENE_POINT3D_INIT (0, *allocated_size - *natural_size, 0)); - } - - *allocated_size = *natural_size; - } + { + *allocated_pos += (*allocated_size - *natural_size); + *allocated_size = *natural_size; + } break; case GTK_ALIGN_CENTER: if (*allocated_size > *natural_size) - { - if (transform) - { - if (orientation == GTK_ORIENTATION_HORIZONTAL) - graphene_matrix_translate (transform, - &GRAPHENE_POINT3D_INIT ((*allocated_size - *natural_size) / 2, 0, 0)); - else - graphene_matrix_translate (transform, - &GRAPHENE_POINT3D_INIT (0, (*allocated_size - *natural_size) / 2, 0)); - } - - *allocated_size = MIN (*allocated_size, *natural_size); - } + { + *allocated_pos += (*allocated_size - *natural_size) / 2; + *allocated_size = MIN (*allocated_size, *natural_size); + } break; } } static void -adjust_for_margin (GtkOrientation orientation, - int start_margin, - int end_margin, - int *minimum_size, - int *natural_size, - graphene_matrix_t *transform, - int *allocated_size) +adjust_for_margin(gint start_margin, + gint end_margin, + gint *minimum_size, + gint *natural_size, + gint *allocated_pos, + gint *allocated_size) { *minimum_size -= (start_margin + end_margin); *natural_size -= (start_margin + end_margin); + *allocated_pos += start_margin; *allocated_size -= (start_margin + end_margin); - - if (transform) - { - if (orientation == GTK_ORIENTATION_HORIZONTAL) - graphene_matrix_translate (transform, - &GRAPHENE_POINT3D_INIT (start_margin, 0, 0)); - else - graphene_matrix_translate (transform, - &GRAPHENE_POINT3D_INIT (0, start_margin, 0)); - } } void @@ -4697,32 +4656,28 @@ gtk_widget_adjust_size_allocation (GtkWidget *widget, GtkOrientation orientation, gint *minimum_size, gint *natural_size, - graphene_matrix_t *transform, + gint *allocated_pos, gint *allocated_size) { GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); if (orientation == GTK_ORIENTATION_HORIZONTAL) { - adjust_for_margin (orientation, - priv->margin.left, + adjust_for_margin (priv->margin.left, priv->margin.right, minimum_size, natural_size, - transform, allocated_size); - adjust_for_align (orientation, - effective_align (priv->halign, _gtk_widget_get_direction (widget)), - natural_size, transform, allocated_size); + allocated_pos, allocated_size); + adjust_for_align (effective_align (priv->halign, _gtk_widget_get_direction (widget)), + natural_size, allocated_pos, allocated_size); } else { - adjust_for_margin (orientation, - priv->margin.top, + adjust_for_margin (priv->margin.top, priv->margin.bottom, minimum_size, natural_size, - transform, allocated_size); - adjust_for_align (orientation, - effective_align (priv->valign, GTK_TEXT_DIR_NONE), - natural_size, transform, allocated_size); + allocated_pos, allocated_size); + adjust_for_align (effective_align (priv->valign, GTK_TEXT_DIR_NONE), + natural_size, allocated_pos, allocated_size); } } diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index 9d4d04fcd7..31356ae5a5 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -304,7 +304,7 @@ void gtk_widget_adjust_size_allocation (GtkWidget *w GtkOrientation orientation, gint *minimum_size, gint *natural_size, - graphene_matrix_t *transform, + gint *allocated_pos, gint *allocated_size); void gtk_widget_adjust_baseline_request (GtkWidget *widget, gint *minimum_baseline, -- 2.30.2